package com.catazzz.springbootstudy.common.security;

import com.catazzz.springbootstudy.common.exception.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @作者: Tao
 * @日期: 2025/1/8
 * @时间: 13:25
 * @描述: 自定义认证入口点类，实现AuthenticationEntryPoint接口 <br><pre>
 *
 *          用于处理未授权访问的情况，当用户尝试访问需要认证的URL时，会使用此类进行处理
 *
 *          AuthenticationEntryPoint用来解决匿名用户访问无权限资源时的异常
 */
@Slf4j
//@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        // 设置响应字符编码
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());

        // 判断请求是否为Ajax请求
        if (isAjaxRequest(request)) {
            // 是Ajax请求，返回JSON格式的错误信息
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.getWriter().write(new ObjectMapper().writeValueAsString(Result.error("请登录")));
        } else {
            // 不是Ajax请求，重定向到登录页面
            response.setContentType(MediaType.TEXT_HTML_VALUE);
            String directPath = request.getContextPath() + "/login.html";
            log.info("重定向到登录页面：{}", directPath);
            response.sendRedirect(directPath);
        }
    }

    /**
     * 判断请求是否为Ajax请求
     * 通过检查请求头中的'X-Requested-With'来确定请求类型
     *
     * @param request HttpServletRequest对象，用于获取请求头信息
     * @return boolean 如果是Ajax请求返回true，否则返回false
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        // 获取请求头中的'X-Requested-With'字段值
        String requestType = request.getHeader("X-Requested-With");
        // 判断请求类型是否为'XMLHttpRequest'
        return "XMLHttpRequest".equals(requestType);
    }
}
